package com.ict.ycwl.clustercalculate.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ict.ycwl.clustercalculate.mapper.AccumulationMapper;
import com.ict.ycwl.clustercalculate.mapper.ErrorPointMapper;
import com.ict.ycwl.clustercalculate.mapper.StoreMapper;
import com.ict.ycwl.clustercalculate.pojo.*;
import com.ict.ycwl.clustercalculate.service.PointService;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static java.lang.Math.toRadians;

/**
 * @author yuhuaame
 */
@Service
public class PointServiceImpl implements PointService {

    @Autowired
    private AccumulationMapper accumulationMapper;

    @Autowired
    private StoreMapper storeMapper;

    @Autowired
    private ErrorPointMapper errorPointMapper;

    //    @Override
    public Object getMapResultPoints1() {
        MapResult result = new MapResult();
        List<MapResultPoint> resultPoints = new ArrayList<>();
        List<Circle> circles = new ArrayList<>();

        //获得聚集区点
        QueryWrapper<Accumulation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        List<Accumulation> accumulations = accumulationMapper.selectList(queryWrapper);
        //获得错误点，用于为下面循环做判断
        QueryWrapper<ErrorPoint> queryWrapper1 = new QueryWrapper<>();
//        queryWrapper1.eq("is_delete", 0).eq("is_exist", 1);
        queryWrapper1.eq("is_delete", 0);
        List<ErrorPoint> errorPoints = errorPointMapper.selectList(queryWrapper1);

        for (int i = 0; i < accumulations.size(); i++) {
            MapResultPoint mapResultPoint = new MapResultPoint();
            ArrayList<Double> arrayList = new ArrayList<Double>();
            arrayList.add(accumulations.get(i).getLongitude());
            arrayList.add(accumulations.get(i).getLatitude());
            mapResultPoint.setLnglat(arrayList);
            mapResultPoint.setName(accumulations.get(i).getAccumulationAddress());
            mapResultPoint.setStyle(i);
            for (ErrorPoint e : errorPoints) {
                if (e.getCurrentStoreLongitude() == accumulations.get(i).getLongitude() && e.getCurrentStoreLatitude() == accumulations.get(i).getLatitude()) {
                    mapResultPoint.setState("error");
                    resultPoints.add(mapResultPoint);
                } else if (e.getPairingStoreLongitude() == accumulations.get(i).getLongitude() && e.getPairingStoreLatitude() == accumulations.get(i).getLatitude()) {
                    mapResultPoint.setState("error");
                    resultPoints.add(mapResultPoint);
                } else {
                    mapResultPoint.setState("center");
                    resultPoints.add(mapResultPoint);
                }
            }

            double rand = 0;

            //获取普通点
            List<Store> ordinaryPoint = storeMapper.getOrdinaryPointByAccumulationId(accumulations.get(i).getAccumulationId());
            for (Store s : ordinaryPoint) {
                MapResultPoint mapResultPoint1 = new MapResultPoint();
                ArrayList<Double> arrayList1 = new ArrayList<>();
                arrayList1.add(s.getLongitude());
                arrayList1.add(s.getLatitude());
                mapResultPoint1.setLnglat(arrayList1);
                mapResultPoint1.setName(s.getStoreAddress());
                mapResultPoint1.setStyle(i);
                for (ErrorPoint e : errorPoints) {
                    if (e.getCurrentStoreLongitude() == s.getLongitude() && e.getCurrentStoreLatitude() == s.getLatitude()) {
                        mapResultPoint1.setState("error");
                        resultPoints.add(mapResultPoint1);
                    } else if (e.getPairingStoreLongitude() == s.getLongitude() && e.getPairingStoreLatitude() == s.getLatitude()) {
                        mapResultPoint1.setState("error");
                        resultPoints.add(mapResultPoint1);
                    } else {
                        mapResultPoint1.setState("ordinary");
                        resultPoints.add(mapResultPoint1);
                    }
                }

                //计算每个商铺距离簇心的距离，以最远距离作为地图的圆面半径
                double v = calculateDistance(s.getLatitude(), s.getLongitude(), accumulations.get(i).getLatitude(), accumulations.get(i).getLongitude());
                if (v > rand) {
                    rand = v;
                }
            }

            ArrayList<Double> a = new ArrayList<Double>();
            a.add(accumulations.get(i).getLongitude());
            a.add(accumulations.get(i).getLatitude());
            circles.add(new Circle(a, rand * 1000));
        }

        result.setPoint(resultPoints);
        result.setSide(circles);

        return result;
    }

    //    @Override
    public Object getMapResultPoints2() {
        MapResult result = new MapResult();
        List<MapResultPoint> resultPoints = new ArrayList<>();
        //获得聚集区点
        QueryWrapper<Accumulation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        List<Accumulation> accumulations = accumulationMapper.selectList(queryWrapper);
        //获得错误点，用于为下面循环做判断
        QueryWrapper<ErrorPoint> queryWrapper1 = new QueryWrapper<>();
//        queryWrapper1.eq("is_delete", 0).eq("is_exist", 1);
        queryWrapper1.eq("is_delete", 0);
        List<ErrorPoint> errorPoints = errorPointMapper.selectList(queryWrapper1);

        //聚集区的集合，其中LngAndLat代表当前聚集区的其中一个商铺，ArrayList<LngAndLat>表示一个聚集区
        ArrayList<ArrayList<LngAndLat>> accumulationStoreList = new ArrayList<>();

        for (int i = 0; i < accumulations.size(); i++) {
            MapResultPoint mapResultPoint = new MapResultPoint();
            Accumulation accumulation = accumulations.get(i);

            ArrayList<Double> arrayList = new ArrayList<Double>();
            arrayList.add(accumulation.getLongitude());
            arrayList.add(accumulation.getLatitude());
            mapResultPoint.setLnglat(arrayList);

            mapResultPoint.setName(accumulation.getAccumulationAddress());
            mapResultPoint.setStyle(i);
            mapResultPoint.setAccumulationId(accumulation.getAccumulationId());
            mapResultPoint.setRouteId(accumulation.getRouteId());
            mapResultPoint.setAreaId(accumulation.getAreaId());

            for (ErrorPoint e : errorPoints) {
                if (e.getCurrentStoreLongitude() == accumulation.getLongitude() && e.getCurrentStoreLatitude() == accumulation.getLatitude()) {
                    mapResultPoint.setState("error");
                    break;
                } else if (e.getPairingStoreLongitude() == accumulation.getLongitude() && e.getPairingStoreLatitude() == accumulation.getLatitude()) {
                    mapResultPoint.setState("error");
                    break;
                } else {
                    mapResultPoint.setState("center");
                }
            }
            resultPoints.add(mapResultPoint);

            //添加该聚集区所包含的商铺
            ArrayList<LngAndLat> list = new ArrayList<>();
            QueryWrapper<Store> storeQueryWrapper = new QueryWrapper<>();
            storeQueryWrapper.eq("accumulation_id", accumulation.getAccumulationId()).eq("is_delete", 0);
            List<Store> stores = storeMapper.selectList(storeQueryWrapper);
            for (Store s : stores) {
                list.add(new LngAndLat(s.getLongitude(), s.getLatitude()));
            }
            accumulationStoreList.add(list);
        }

        //添加剩余错误点
//        for (ErrorPoint e : errorPoints) {
//            MapResultPoint mapResultPoint = new MapResultPoint();
//            QueryWrapper<Store> queryWrapper2 = new QueryWrapper<>();
//            queryWrapper2.eq("is_delete", 0).eq("longitude", e.getCurrentStoreLongitude()).eq("latitude", e.getCurrentStoreLatitude());
//            Store store = null;
//            try {
//                store = storeMapper.selectList(queryWrapper2).get(0);
//            } catch (IndexOutOfBoundsException i) {
//                throw new IllegalAccessError("商铺可能已被删除");
//            }
//            addRemainderErrorPoints(resultPoints, mapResultPoint, store);
//
//            MapResultPoint mapResultPoint1 = new MapResultPoint();
//            QueryWrapper<Store> queryWrapper3 = new QueryWrapper<>();
//            queryWrapper3.eq("is_delete", 0).eq("longitude", e.getPairingStoreLongitude()).eq("latitude", e.getPairingStoreLatitude());
//            Store store1 = null;
//            try {
//                store1 = storeMapper.selectList(queryWrapper3).get(0);
//            } catch (IndexOutOfBoundsException i) {
//                throw new IllegalAccessError("商铺可能已被删除");
//            }
//            addRemainderErrorPoints(resultPoints, mapResultPoint1, store1);
//        }
        for (ErrorPoint e : errorPoints) {
            LngAndLat l1 = new LngAndLat(e.getCurrentStoreLongitude(), e.getCurrentStoreLatitude());
            LngAndLat l2 = new LngAndLat(e.getPairingStoreLongitude(), e.getPairingStoreLatitude());
            for (ArrayList<LngAndLat> arrayList : accumulationStoreList) {
                if (arrayList.contains(l1) && arrayList.contains(l2)) {
                    MapResultPoint mapResultPoint = new MapResultPoint();
                    QueryWrapper<Store> queryWrapper2 = new QueryWrapper<>();
                    queryWrapper2.eq("is_delete", 0).eq("longitude", e.getCurrentStoreLongitude()).eq("latitude", e.getCurrentStoreLatitude());
                    Store store = null;
                    try {
                        store = storeMapper.selectList(queryWrapper2).get(0);
                    } catch (IndexOutOfBoundsException i) {
                        throw new IllegalAccessError("商铺可能已被删除");
                    }
                    addRemainderErrorPoints(resultPoints, mapResultPoint, store);

                    MapResultPoint mapResultPoint1 = new MapResultPoint();
                    QueryWrapper<Store> queryWrapper3 = new QueryWrapper<>();
                    queryWrapper3.eq("is_delete", 0).eq("longitude", e.getPairingStoreLongitude()).eq("latitude", e.getPairingStoreLatitude());
                    Store store1 = null;
                    try {
                        store1 = storeMapper.selectList(queryWrapper3).get(0);
                    } catch (IndexOutOfBoundsException i) {
                        throw new IllegalAccessError("商铺可能已被删除");
                    }
                    addRemainderErrorPoints(resultPoints, mapResultPoint1, store1);
                }
            }
        }

        result.setPoint(resultPoints);
        return result;
    }

    @Override
    public Object getMapResultPoints() {
        MapResult result = new MapResult();
        List<MapResultPoint> resultPoints = new ArrayList<>();
        //获得聚集区点
        QueryWrapper<Accumulation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        List<Accumulation> accumulations = accumulationMapper.selectList(queryWrapper);
        //获得错误点，用于为下面循环做判断
        QueryWrapper<ErrorPoint> queryWrapper1 = new QueryWrapper<>();
//        queryWrapper1.eq("is_delete", 0).eq("is_exist", 1);
        queryWrapper1.eq("is_delete", 0);
        List<ErrorPoint> errorPoints = errorPointMapper.selectList(queryWrapper1);

        //商铺的集合，其中LngAndLat代表当前聚集区的其中一个商铺，ArrayList<LngAndLat>表示一个聚集区
        ArrayList<ArrayList<LngAndLat>> accumulationStoreList = new ArrayList<>();
        //聚集区的集合
        ArrayList<LngAndLat> accumulationList = new ArrayList<>();

        for (Accumulation accumulation : accumulations) {
            accumulationList.add(new LngAndLat(accumulation.getLongitude(), accumulation.getLatitude()));

            //添加该聚集区所包含的商铺
            ArrayList<LngAndLat> list = new ArrayList<>();
            QueryWrapper<Store> storeQueryWrapper = new QueryWrapper<>();
            storeQueryWrapper.eq("accumulation_id", accumulation.getAccumulationId()).eq("is_delete", 0);
            List<Store> stores = storeMapper.selectList(storeQueryWrapper);
            for (Store s : stores) {
                list.add(new LngAndLat(s.getLongitude(), s.getLatitude()));
            }
            accumulationStoreList.add(list);
        }

        //添加错误点
        for (ErrorPoint e : errorPoints) {
            LngAndLat l1 = new LngAndLat(e.getCurrentStoreLongitude(), e.getCurrentStoreLatitude());
            LngAndLat l2 = new LngAndLat(e.getPairingStoreLongitude(), e.getPairingStoreLatitude());
            for (ArrayList<LngAndLat> arrayList : accumulationStoreList) {
                if (arrayList.contains(l1) && arrayList.contains(l2)) {
                    MapResultPoint mapResultPoint = new MapResultPoint();
                    QueryWrapper<Store> queryWrapper2 = new QueryWrapper<>();
                    queryWrapper2.eq("is_delete", 0).eq("longitude", e.getCurrentStoreLongitude()).eq("latitude", e.getCurrentStoreLatitude());
                    Store store = null;
                    try {
                        store = storeMapper.selectList(queryWrapper2).get(0);
                    } catch (IndexOutOfBoundsException i) {
                        throw new IllegalAccessError("商铺可能已被删除");
                    }
                    addRemainderErrorPoints(resultPoints, mapResultPoint, store);

                    MapResultPoint mapResultPoint1 = new MapResultPoint();
                    QueryWrapper<Store> queryWrapper3 = new QueryWrapper<>();
                    queryWrapper3.eq("is_delete", 0).eq("longitude", e.getPairingStoreLongitude()).eq("latitude", e.getPairingStoreLatitude());
                    Store store1 = null;
                    try {
                        store1 = storeMapper.selectList(queryWrapper3).get(0);
                    } catch (IndexOutOfBoundsException i) {
                        throw new IllegalAccessError("商铺可能已被删除");
                    }
                    addRemainderErrorPoints(resultPoints, mapResultPoint1, store1);

                    //如果accumulationList中存在这两个点，则删除这两个点，因为虽然点有可能是聚集区，这两个点已经被标记为了error
                    accumulationList.remove(l1);
                    accumulationList.remove(l2);
                }
            }
        }

        int i = 1;
        //将过滤后的聚集区集合加到result里
        for (LngAndLat lngAndLat : accumulationList) {
            MapResultPoint mapResultPoint = new MapResultPoint();
            QueryWrapper<Accumulation> accumulationQueryWrapper = new QueryWrapper<>();
            accumulationQueryWrapper.eq("is_delete", 0).eq("longitude", lngAndLat.getLongitude()).eq("latitude", lngAndLat.getLatitude());
            Accumulation accumulation = accumulationMapper.selectOne(accumulationQueryWrapper);

            ArrayList<Double> arrayList = new ArrayList<Double>();
            arrayList.add(lngAndLat.getLongitude());
            arrayList.add(lngAndLat.getLatitude());
            mapResultPoint.setLnglat(arrayList);
            mapResultPoint.setName(accumulation.getAccumulationAddress());
            mapResultPoint.setStyle(i++);
            mapResultPoint.setAccumulationId(accumulation.getAccumulationId());
            mapResultPoint.setRouteId(accumulation.getRouteId());
            mapResultPoint.setAreaId(accumulation.getAreaId());
            mapResultPoint.setState("center");

            resultPoints.add(mapResultPoint);
        }

        result.setPoint(resultPoints);
        return result;
    }

    private void addRemainderErrorPoints(List<MapResultPoint> resultPoints, MapResultPoint mapResultPoint, Store store) {
        ArrayList<Double> arrayList = new ArrayList<Double>();
        arrayList.add(store.getLongitude());
        arrayList.add(store.getLatitude());
        mapResultPoint.setLnglat(arrayList);
        mapResultPoint.setName(store.getStoreAddress());
        mapResultPoint.setAccumulationId(store.getAccumulationId());
        mapResultPoint.setRouteId(store.getRouteId());
        mapResultPoint.setAreaId(store.getAreaId());
        mapResultPoint.setState("error");
        if(!resultPoints.contains(mapResultPoint)){
            resultPoints.add(mapResultPoint);
        }
    }

    @Override
    public List<ListPoint> getListResultPoints() {
        List<ListPoint> listPoints = new ArrayList<>();

        QueryWrapper<Accumulation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        List<Accumulation> accumulations = accumulationMapper.selectList(queryWrapper);
        for (Accumulation accumulation : accumulations) {
            List<Store> stores = storeMapper.selectList(new QueryWrapper<Store>().eq("accumulation_id", accumulation.getAccumulationId()));
            for (Store s : stores) {
                ListPoint listPoint = new ListPoint();
                listPoint.setName(s.getStoreAddress());
                listPoint.setAccumulation(accumulation.getAccumulationName());
                listPoints.add(listPoint);
            }
        }

        return listPoints;
    }

//    @Override
//    public int checkErrorPoint(String areaName) {
//        List<LngAndLat> clusterCenters = accumulationMapper.selectAllByAreaName(areaName);
//        //查询error_point表里的所有数据
//        QueryWrapper<ErrorPoint> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("is_delete", 0);
//        List<ErrorPoint> ep = errorPointMapper.selectList(queryWrapper);
//
//        //转换ep数组的格式
//        List<LngAndLat> errorPoints = new ArrayList<>();
//        for (ErrorPoint e : ep) {
//            LngAndLat l1 = new LngAndLat();
//            l1.setLongitude(e.getCurrentStoreLongitude());
//            l1.setLatitude(e.getCurrentStoreLatitude());
//            if (!errorPoints.contains(l1)) {
//                errorPoints.add(l1);
//            }
//            LngAndLat l2 = new LngAndLat();
//            l2.setLongitude(e.getPairingStoreLongitude());
//            l2.setLatitude(e.getPairingStoreLatitude());
//            if (!errorPoints.contains(l2)) {
//                errorPoints.add(l2);
//            }
//        }
//
//        int flag = 0;
//
//        //检查是否有错误点
//        for (LngAndLat d : clusterCenters) {
//            List<LngAndLat> lngAndLats = storeMapper.selectByLongAndLat(d.getLongitude(), d.getLatitude());
//            for (LngAndLat ll : lngAndLats) {
//                if (errorPoints.contains(ll)) {
//                    for (LngAndLat l : lngAndLats) {
//                        if (errorPoints.contains(l)) {
//                            //有错误点，但还要匹配一下表里是否有这条数据
//                            QueryWrapper<ErrorPoint> queryWrapper1 = new QueryWrapper<>();
//                            queryWrapper1.eq("current_store_longitude", ll.getLongitude()).eq("current_store_latitude", ll.getLatitude()).eq("pairing_store_longitude", l.getLongitude()).eq("pairing_store_latitude", l.getLatitude());
//                            ErrorPoint errorPoint = errorPointMapper.selectOne(queryWrapper1);
//                            if (errorPoint != null) {
//                                UpdateWrapper<ErrorPoint> updateWrapper = new UpdateWrapper<>();
//                                updateWrapper.eq("current_store_longitude", ll.getLongitude()).eq("current_store_latitude", ll.getLatitude()).eq("pairing_store_longitude", l.getLongitude()).eq("pairing_store_latitude", l.getLatitude()).set("is_exist", 1);
//                                errorPointMapper.update(null, updateWrapper);
//                                flag++;
//                            }
//                        }
//                    }
//                }
//            }
//        }
//
//        return flag;
//    }
//
//    @Override
//    public int checkErrorPoints() {
//        List<String> strings = storeMapper.selectAllAreaName();
//
//        //将error_point表里所有数据的is_exist字段的值改为0
//        UpdateWrapper<ErrorPoint> updateWrapper = new UpdateWrapper<>();
//        updateWrapper.eq("is_delete", 0).set("is_exist", 0);
//        errorPointMapper.update(null, updateWrapper);
//
//        int flag = 0;
//
//        for (String s : strings) {
//            int i = checkErrorPoint(s);
//            flag += i;
//        }
//
//        return flag;
//    }

    @Override
    public int checkErrorPoints() {
        List<MapResultPoint> resultPoints = new ArrayList<>();
        //获得聚集区点
        QueryWrapper<Accumulation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        List<Accumulation> accumulations = accumulationMapper.selectList(queryWrapper);
        //获得错误点，用于为下面循环做判断
        QueryWrapper<ErrorPoint> queryWrapper1 = new QueryWrapper<>();
//        queryWrapper1.eq("is_delete", 0).eq("is_exist", 1);
        queryWrapper1.eq("is_delete", 0);
        List<ErrorPoint> errorPoints = errorPointMapper.selectList(queryWrapper1);

        //商铺的集合，其中LngAndLat代表当前聚集区的其中一个商铺，ArrayList<LngAndLat>表示一个聚集区
        ArrayList<ArrayList<LngAndLat>> accumulationStoreList = new ArrayList<>();

        for (Accumulation accumulation : accumulations) {
            //添加该聚集区所包含的商铺
            ArrayList<LngAndLat> list = new ArrayList<>();
            QueryWrapper<Store> storeQueryWrapper = new QueryWrapper<>();
            storeQueryWrapper.eq("accumulation_id", accumulation.getAccumulationId()).eq("is_delete", 0);
            List<Store> stores = storeMapper.selectList(storeQueryWrapper);
            for (Store s : stores) {
                list.add(new LngAndLat(s.getLongitude(), s.getLatitude()));
            }
            accumulationStoreList.add(list);
        }

        //添加错误点
        for (ErrorPoint e : errorPoints) {
            LngAndLat l1 = new LngAndLat(e.getCurrentStoreLongitude(), e.getCurrentStoreLatitude());
            LngAndLat l2 = new LngAndLat(e.getPairingStoreLongitude(), e.getPairingStoreLatitude());
            for (ArrayList<LngAndLat> arrayList : accumulationStoreList) {
                if (arrayList.contains(l1) && arrayList.contains(l2)) {
                    MapResultPoint mapResultPoint = new MapResultPoint();
                    QueryWrapper<Store> queryWrapper2 = new QueryWrapper<>();
                    queryWrapper2.eq("is_delete", 0).eq("longitude", e.getCurrentStoreLongitude()).eq("latitude", e.getCurrentStoreLatitude());
                    Store store = null;
                    try {
                        store = storeMapper.selectList(queryWrapper2).get(0);
                    } catch (IndexOutOfBoundsException i) {
                        throw new IllegalAccessError("商铺可能已被删除");
                    }
                    addRemainderErrorPoints(resultPoints, mapResultPoint, store);

                    MapResultPoint mapResultPoint1 = new MapResultPoint();
                    QueryWrapper<Store> queryWrapper3 = new QueryWrapper<>();
                    queryWrapper3.eq("is_delete", 0).eq("longitude", e.getPairingStoreLongitude()).eq("latitude", e.getPairingStoreLatitude());
                    Store store1 = null;
                    try {
                        store1 = storeMapper.selectList(queryWrapper3).get(0);
                    } catch (IndexOutOfBoundsException i) {
                        throw new IllegalAccessError("商铺可能已被删除");
                    }
                    addRemainderErrorPoints(resultPoints, mapResultPoint1, store1);
                }
            }
        }

        return resultPoints.size();
    }

    //    @Override
    public List<ListErrorCluster> getErrorPoints1() {
        //获取错误点数组
        QueryWrapper<ErrorPoint> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("is_delete", 0).eq("is_exist", 1);
        queryWrapper.eq("is_delete", 0);
        List<ErrorPoint> errorPoints = errorPointMapper.selectList(queryWrapper);

        //根据错误点获取所有含有错误点的聚集区名字
        List<String> accumulationName = new ArrayList<>();
        for (ErrorPoint errorPoint : errorPoints) {
            QueryWrapper<Store> s = new QueryWrapper<>();
            s.eq("longitude", errorPoint.getCurrentStoreLongitude()).eq("latitude", errorPoint.getCurrentStoreLatitude()).eq("is_delete", 0);
            Store store = storeMapper.selectList(s).get(0);

            QueryWrapper<Accumulation> q = new QueryWrapper<>();
            q.eq("accumulation_id", store.getAccumulationId());
            Accumulation accumulation = accumulationMapper.selectOne(q);

            if (!accumulationName.contains(accumulation.getAccumulationName())) {
                accumulationName.add(accumulation.getAccumulationName());
            }
        }

        List<ListErrorCluster> listErrorClusters = new ArrayList<>();
        //将错误点装到对应的聚集区
        for (String s : accumulationName) {
            ListErrorCluster listErrorCluster = new ListErrorCluster();
            listErrorCluster.setAccumulationName(s);
            listErrorCluster.setData(new ArrayList<>());

            for (ErrorPoint errorPoint : errorPoints) {
                //当前商铺
                QueryWrapper<Store> q = new QueryWrapper<>();
                q.eq("longitude", errorPoint.getCurrentStoreLongitude()).eq("latitude", errorPoint.getCurrentStoreLatitude()).eq("is_delete", 0);
                Store store = storeMapper.selectList(q).get(0);

                QueryWrapper<Accumulation> a = new QueryWrapper<>();
                a.eq("accumulation_id", store.getAccumulationId());
                Accumulation accumulation = accumulationMapper.selectOne(a);

                if (accumulation.getAccumulationName().equals(s)) {
                    boolean exist = false;
                    for (int i = 0; i < listErrorCluster.getData().size(); i++) {
                        if (listErrorCluster.getData().get(i).getName().equals(store.getStoreAddress())) {
                            exist = true;
                            break;
                        }
                    }
                    if (!exist) {
                        ListErrorPointFather current = new ListErrorPointFather(store.getLongitude(), store.getLatitude(), store.getStoreAddress(), new ArrayList<>());
                        listErrorCluster.getData().add(current);
                    }
                }

                //配对商铺
                QueryWrapper<Store> q1 = new QueryWrapper<>();
                q1.eq("longitude", errorPoint.getPairingStoreLongitude()).eq("latitude", errorPoint.getPairingStoreLatitude()).eq("is_delete", 0);
                Store store1 = storeMapper.selectList(q1).get(0);

                QueryWrapper<Accumulation> a1 = new QueryWrapper<>();
                a1.eq("accumulation_id", store1.getAccumulationId());
                Accumulation accumulation1 = accumulationMapper.selectOne(a1);

                if (accumulation1.getAccumulationName().equals(s)) {
                    ListErrorPointSon paring = new ListErrorPointSon(store1.getLongitude(), store1.getLatitude(), store1.getStoreAddress());
                    //找到配对商铺的父节点
                    for (int i = 0; i < listErrorCluster.getData().size(); i++) {
                        if (listErrorCluster.getData().get(i).getName().equals(store.getStoreAddress())) {
                            listErrorCluster.getData().get(i).getSon().add(paring);
                            int number = listErrorCluster.getNumber();
                            listErrorCluster.setNumber(number + 1);
                        }
                    }
                }
            }

//            listErrorCluster.setNumber(listErrorCluster.getData().size());

            listErrorClusters.add(listErrorCluster);
        }

        return listErrorClusters;
    }

    @Override
    public List<ListErrorCluster> getErrorPoints() {
        //获得聚集区点
        QueryWrapper<Accumulation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        List<Accumulation> accumulations = accumulationMapper.selectList(queryWrapper);
        //获得错误点，用于为下面循环做判断
        QueryWrapper<ErrorPoint> queryWrapper1 = new QueryWrapper<>();
//        queryWrapper1.eq("is_delete", 0).eq("is_exist", 1);
        queryWrapper1.eq("is_delete", 0);
        List<ErrorPoint> errorPointsList = errorPointMapper.selectList(queryWrapper1);

        //商铺的集合，其中LngAndLat代表当前聚集区的其中一个商铺，ArrayList<LngAndLat>表示一个聚集区
        ArrayList<ArrayList<LngAndLat>> accumulationStoreList = new ArrayList<>();

        for (Accumulation accumulation : accumulations) {
            //添加该聚集区所包含的商铺
            ArrayList<LngAndLat> list = new ArrayList<>();
            QueryWrapper<Store> storeQueryWrapper = new QueryWrapper<>();
            storeQueryWrapper.eq("accumulation_id", accumulation.getAccumulationId()).eq("is_delete", 0);
            List<Store> stores = storeMapper.selectList(storeQueryWrapper);
            for (Store s : stores) {
                list.add(new LngAndLat(s.getLongitude(), s.getLatitude()));
            }
            accumulationStoreList.add(list);
        }

        //创建错误点数组
        List<ErrorPoint> errorPoints = new ArrayList<>();
        //添加错误点
        for (ErrorPoint e : errorPointsList) {
            LngAndLat l1 = new LngAndLat(e.getCurrentStoreLongitude(), e.getCurrentStoreLatitude());
            LngAndLat l2 = new LngAndLat(e.getPairingStoreLongitude(), e.getPairingStoreLatitude());
            for (ArrayList<LngAndLat> arrayList : accumulationStoreList) {
                if (arrayList.contains(l1) && arrayList.contains(l2)) {
                    errorPoints.add(e);
                }
            }
        }

        //根据错误点获取所有含有错误点的聚集区名字
        List<String> accumulationName = new ArrayList<>();
        for (ErrorPoint errorPoint : errorPoints) {
            QueryWrapper<Store> s = new QueryWrapper<>();
            s.eq("longitude", errorPoint.getCurrentStoreLongitude()).eq("latitude", errorPoint.getCurrentStoreLatitude()).eq("is_delete", 0);
            Store store = storeMapper.selectList(s).get(0);

            QueryWrapper<Accumulation> q = new QueryWrapper<>();
            q.eq("accumulation_id", store.getAccumulationId());
            Accumulation accumulation = accumulationMapper.selectOne(q);

            if (!accumulationName.contains(accumulation.getAccumulationName())) {
                accumulationName.add(accumulation.getAccumulationName());
            }
        }

        List<ListErrorCluster> listErrorClusters = new ArrayList<>();
        //将错误点装到对应的聚集区
        for (String aName : accumulationName) {
            HashMap<LngAndLat, ArrayList<LngAndLat>> map = new HashMap<>();
            for (ErrorPoint errorPoint : errorPoints) {
                QueryWrapper<Store> s = new QueryWrapper<>();
                s.eq("longitude", errorPoint.getCurrentStoreLongitude()).eq("latitude", errorPoint.getCurrentStoreLatitude()).eq("is_delete", 0);
                Store store = storeMapper.selectList(s).get(0);

                QueryWrapper<Accumulation> q = new QueryWrapper<>();
                q.eq("accumulation_id", store.getAccumulationId());
                Accumulation accumulation = accumulationMapper.selectOne(q);
                //判断当前遍历的errorPoint元素的起始坐标点的所属聚集区，是否等于当前遍历的aName
                if (accumulation.getAccumulationName().equals(aName)) {
                    LngAndLat key = new LngAndLat(store.getLongitude(), store.getLatitude());
                    LngAndLat value = new LngAndLat(errorPoint.getPairingStoreLongitude(), errorPoint.getPairingStoreLatitude());
                    if (map.containsKey(key)) {
                        map.get(key).add(value);
                    } else {
                        ArrayList<LngAndLat> list = new ArrayList<>();
                        list.add(value);
                        map.put(key, list);
                    }
                }
            }

            ListErrorCluster listErrorCluster = new ListErrorCluster();
            List<ListErrorPointFather> data = new ArrayList<>();
            Set<Map.Entry<LngAndLat, ArrayList<LngAndLat>>> entries = map.entrySet();

            //一个entry为一个ListErrorPointFather
            for (Map.Entry<LngAndLat, ArrayList<LngAndLat>> entry : entries) {
                LngAndLat key = entry.getKey();

                QueryWrapper<Store> s = new QueryWrapper<>();
                s.eq("longitude", key.getLongitude()).eq("latitude", key.getLatitude()).eq("is_delete", 0);
                Store store = storeMapper.selectList(s).get(0);

                ListErrorPointFather father = new ListErrorPointFather();
                father.setLongitude(key.getLongitude());
                father.setLatitude(key.getLatitude());
                father.setName(store.getStoreAddress());
                father.setSon(new ArrayList<>());

                ArrayList<LngAndLat> value = entry.getValue();
                for (LngAndLat l : value) {
                    QueryWrapper<Store> storeQueryWrapper = new QueryWrapper<>();
                    storeQueryWrapper.eq("longitude", l.getLongitude()).eq("latitude", l.getLatitude()).eq("is_delete", 0);
                    Store store1 = storeMapper.selectList(storeQueryWrapper).get(0);
                    father.getSon().add(new ListErrorPointSon(store1.getLongitude(), store1.getLatitude(), store1.getStoreAddress()));
                }

                listErrorCluster.setNumber(listErrorCluster.getNumber() + value.size());

                data.add(father);
            }

            listErrorCluster.setData(data);
            listErrorCluster.setAccumulationName(aName);

            listErrorClusters.add(listErrorCluster);
        }

        return listErrorClusters;
    }

    @Override
    public List<Accumulation> getClosestPoints(double longitude, double latitude) {
        QueryWrapper<Store> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("longitude", longitude).eq("latitude", latitude).eq("is_delete", 0);
        Store store = storeMapper.selectList(queryWrapper).get(0);

        //找出当前商铺点所在大区里的所有聚集区
        QueryWrapper<Accumulation> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("area_name", store.getAreaName()).eq("is_delete", 0);
        List<Accumulation> accumulations = accumulationMapper.selectList(queryWrapper1);

        //计算所有经纬度与目标经纬度的距离
        List<DistanceEntry> distanceEntryList = new ArrayList<>();
        for (Accumulation a : accumulations) {
            double v = calculateDistance(latitude, longitude, a.getLatitude(), a.getLongitude());
            distanceEntryList.add(new DistanceEntry(a, v));
        }

        //根据距离排序
        Collections.sort(distanceEntryList);

        //取最近的三个经纬度
        List<Accumulation> nearestLatLng = new ArrayList<>();
        for (int i = 1; i < Math.min(4, distanceEntryList.size()); i++) {
            nearestLatLng.add(distanceEntryList.get(i).getAccumulation());
        }

        return nearestLatLng;
    }

    @Override
    public int updateStoreAccumulationId(double longitude, double latitude, Long accumulationId) {
        UpdateWrapper<Store> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("longitude", longitude).eq("latitude", latitude).eq("is_delete", 0).set("accumulation_id", accumulationId);
        return storeMapper.update(null, updateWrapper);
    }

    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        // 地球半径
        double r = 6371.0;

        double dLat = toRadians(lat2 - lat1);
        double dLon = toRadians(lon2 - lon1);

        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                        Math.sin(dLon / 2) * Math.sin(dLon / 2);

        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        // 返回距离
        return r * c;
    }

}
